﻿using System;
using LegoBotPrima.Actions;
using LegoBotPrimaAbstractions;
using LegoBotPrimaAbstractions.Extensions;
using LegoBotPrimaTests.Utils;
using Moq;
using NUnit.Framework;

namespace LegoBotPrimaTests
{
    [TestFixture]
    public class Rotate360BotAction_Fixture : BaseFixture
    {

        #region Mock Dependencies

        private bool _stopHasBeenCalled;
        public void Mock_ILegoBotPrimaWorkflow(Mock<ILegoBotPrimaWorkflow> mock)
        {
            mock.Setup(w => w.Stop()).Callback(() => this._stopHasBeenCalled = true);
        }
        #endregion

        private Rotate360BotAction GetRotate360BotAction(double angle, RotationDirection direction)
        {
            var action = new Rotate360BotAction
                             {
                                 PreDefinedRotationAngle = angle, 
                                 PreDefinedRotationDirection = direction,
                                 Workflow = GetMock<ILegoBotPrimaWorkflow>(Mock_ILegoBotPrimaWorkflow), 
                                 Logger = GetMock<IWorkflowLogger>()
                             }; 
            action.MarkStart();
            action.Initialize();
            return action;
        }




        [Test]
        public void Angle_To_Go_Is_Defined_As_Expected_Case_1()
        {

            var action = GetRotate360BotAction(360, RotationDirection.Clockwise);

            Config.Instance = new ChangedConfig { MinDistance = 40 };
            this._stopHasBeenCalled = false;


            action.OnCompassChanged(139, new DateTime(2010, 7, 27, 3, 55, 57, 967));
            action.OnCompassChanged(141, new DateTime(2010, 7, 27, 3, 55, 58, 981));
            action.OnDistanceChanged(255, new DateTime(2010, 7, 27, 3, 55, 59, 456));
            action.OnCompassChanged(256, new DateTime(2010, 7, 27, 3, 56, 0, 32));
            action.OnCompassChanged(318, new DateTime(2010, 7, 27, 3, 56, 1, 117));
            action.OnCompassChanged(9, new DateTime(2010, 7, 27, 3, 56, 2, 96));
            action.OnDistanceChanged(22, new DateTime(2010, 7, 27, 3, 56, 2, 617));
            action.OnCompassChanged(68, new DateTime(2010, 7, 27, 3, 56, 3, 154));
            action.OnDistanceChanged(24, new DateTime(2010, 7, 27, 3, 56, 3, 754));
            action.OnCompassChanged(132, new DateTime(2010, 7, 27, 3, 56, 4, 298));
            action.OnDistanceChanged(8, new DateTime(2010, 7, 27, 3, 56, 4, 836));
            Assert.That(this._stopHasBeenCalled, Is.False);
            action.OnCompassChanged(236, new DateTime(2010, 7, 27, 3, 56, 5, 241));
            Assert.That(this._stopHasBeenCalled, Is.True);
            Assert.That(action.RequestedNextAction, Is.Not.Null);
            Assert.That(action.RequestedNextAction, Is.InstanceOf(typeof(GoToAngleBotAction)));
            Assert.That(((GoToAngleBotAction)action.RequestedNextAction).Angle, Is.InRange(141, 256));
        }

        [Test]
        public void Angle_To_Go_Is_Defined_As_Expected_Case_2()
        {

            var action = GetRotate360BotAction(90, RotationDirection.Counterclockwise);

            Config.Instance = new ChangedConfig { MinDistance = 40 };
            this._stopHasBeenCalled = false;


            action.OnCompassChanged(85, new DateTime(2010, 7, 28, 21, 59, 7, 753));
            action.OnCompassChanged(27, new DateTime(2010, 7, 28, 21, 59, 8, 748));
            action.OnDistanceChanged(42, new DateTime(2010, 7, 28, 21, 59, 9, 304));
            Assert.That(this._stopHasBeenCalled, Is.False);
            action.OnCompassChanged(342, new DateTime(2010, 7, 28, 21, 59, 9, 864));

            Console.WriteLine(((GoToAngleBotAction)action.RequestedNextAction).Angle);
            var range = new DateTime(2010, 7, 28, 21, 59, 9, 864) - new DateTime(2010, 7, 28, 21, 59, 8, 748);
            var ofend = new DateTime(2010, 7, 28, 21, 59, 9, 864) - new DateTime(2010, 7, 28, 21, 59, 9, 304);

            Console.WriteLine( 27 - (ofend.TotalMilliseconds / range.TotalMilliseconds)*45);

            Assert.That(this._stopHasBeenCalled, Is.True);
            Assert.That(action.RequestedNextAction, Is.Not.Null);
            Assert.That(action.RequestedNextAction, Is.InstanceOf(typeof(GoToAngleBotAction)));
            //Assert.That(((GoToAngleBotAction)action.RequestedNextAction).Angle, Is.InRange(141, 256));
        }





    }
}
